package org.jeecg.modules.ws.controller;

import java.io.*;
import java.lang.reflect.InvocationTargetException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.net.URLDecoder;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.jeecg.common.api.vo.Result;
import org.jeecg.common.exception.JeecgBootException;
import org.jeecg.common.system.query.QueryGenerator;
import org.jeecg.common.aspect.annotation.AutoLog;
import org.jeecg.common.util.oConvertUtils;

import java.util.Date;
import java.util.stream.Collectors;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import lombok.extern.slf4j.Slf4j;
import org.jeecg.common.system.base.controller.JeecgController;
import org.jeecg.common.util.oss.OssBootUtil;
import org.jeecg.modules.ws.common.WsFileEnum;
import org.jeecg.modules.ws.common.WsFileTemplateEnum;
import org.jeecg.modules.ws.dto.CwbbDownloadDto;
import org.jeecg.modules.ws.entity.*;
import org.jeecg.modules.ws.service.IWsCompanyService;
import org.jeecg.modules.ws.service.IWsEmployeeService;
import org.jeecg.modules.ws.service.IWsFileService;
import org.jeecgframework.poi.excel.ExcelImportUtil;
import org.jeecgframework.poi.excel.def.NormalExcelConstants;
import org.jeecgframework.poi.excel.entity.ExportParams;
import org.jeecgframework.poi.excel.entity.ImportParams;
import org.jeecgframework.poi.excel.view.JeecgEntityExcelView;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.FileSystemResource;
import org.springframework.core.io.InputStreamResource;
import org.springframework.core.io.Resource;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.MultipartHttpServletRequest;
import org.springframework.web.servlet.ModelAndView;
import com.alibaba.fastjson.JSON;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;

/**
 * @Description: 附件信息
 * @Author: jeecg-boot
 * @Date: 2025-04-21
 * @Version: V1.0
 */
@Slf4j
@Api(tags = "附件信息")
@RestController
@RequestMapping("/wsFile")
public class WsFileController extends JeecgController<WsFile, IWsFileService> {
    @Autowired
    private IWsFileService wsFileService;
    @Autowired
    private IWsEmployeeService employeeService;

    /**
     * 分页列表查询
     *
     * @param wsFile
     * @param pageNo
     * @param pageSize
     * @param req
     * @return
     */
    @AutoLog(value = "附件信息-分页列表查询")
    @ApiOperation(value = "附件信息-分页列表查询", notes = "附件信息-分页列表查询")
    @GetMapping(value = "/list")
    public Result<?> queryPageList(WsFile wsFile,
                                   @RequestParam(name = "pageNo", defaultValue = "1") Integer pageNo,
                                   @RequestParam(name = "pageSize", defaultValue = "10") Integer pageSize,
                                   HttpServletRequest req) {
        QueryWrapper<WsFile> queryWrapper = QueryGenerator.initQueryWrapper(wsFile, req.getParameterMap());
        Page<WsFile> page = new Page<WsFile>(pageNo, pageSize);
        IPage<WsFile> pageList = wsFileService.page(page, queryWrapper);
        return Result.OK(pageList);
    }

    /**
     * 添加
     *
     * @param wsFile
     * @return
     */
    @AutoLog(value = "附件信息-添加")
    @ApiOperation(value = "附件信息-添加", notes = "附件信息-添加")
    @PostMapping(value = "/add")
    public Result<?> add(@RequestBody WsFile wsFile) {
        wsFileService.save(wsFile);
        return Result.OK("添加成功！");
    }

    /**
     * 编辑
     *
     * @param wsFile
     * @return
     */
    @AutoLog(value = "附件信息-编辑")
    @ApiOperation(value = "附件信息-编辑", notes = "附件信息-编辑")
    @PutMapping(value = "/edit")
    public Result<?> edit(@RequestBody WsFile wsFile) {
        wsFileService.updateById(wsFile);
        return Result.OK("编辑成功!");
    }

    /**
     * 通过id删除
     *
     * @param id
     * @return
     */
    @AutoLog(value = "附件信息-通过id删除")
    @ApiOperation(value = "附件信息-通过id删除", notes = "附件信息-通过id删除")
    @DeleteMapping(value = "/delete")
    public Result<?> delete(@RequestParam(name = "id", required = true) String id) {
        wsFileService.removeById(id);
        return Result.OK("删除成功!");
    }

    /**
     * 批量删除
     *
     * @param ids
     * @return
     */
    @AutoLog(value = "附件信息-批量删除")
    @ApiOperation(value = "附件信息-批量删除", notes = "附件信息-批量删除")
    @DeleteMapping(value = "/deleteBatch")
    public Result<?> deleteBatch(@RequestParam(name = "ids", required = true) String ids) {
        this.wsFileService.removeByIds(Arrays.asList(ids.split(",")));
        return Result.OK("批量删除成功！");
    }

    /**
     * 通过id查询
     *
     * @param id
     * @return
     */
    @AutoLog(value = "附件信息-通过id查询")
    @ApiOperation(value = "附件信息-通过id查询", notes = "附件信息-通过id查询")
    @GetMapping(value = "/queryById")
    public Result<?> queryById(@RequestParam(name = "id", required = true) String id) {
        WsFile wsFile = wsFileService.getById(id);
        return Result.OK(wsFile);
    }

    /**
     * 导出excel
     *
     * @param request
     * @param wsFile
     */
    @RequestMapping(value = "/exportXls")
    public ModelAndView exportXls(HttpServletRequest request, WsFile wsFile) {
        return super.exportXls(request, wsFile, WsFile.class, "附件信息");
    }

    /**
     * 通过excel导入数据
     *
     * @param request
     * @param response
     * @return
     */
    @RequestMapping(value = "/importExcel", method = RequestMethod.POST)
    public Result<?> importExcel(HttpServletRequest request, HttpServletResponse response) {
        return super.importExcel(request, response, WsFile.class);
    }

    /**
     * 上传附件
     *
     * @param file
     * @param request
     * @return
     */
    @RequestMapping(value = "/uploadFile", method = RequestMethod.POST)
    public Result<?> uploadFile(MultipartFile file, HttpServletRequest request) {
        String bizName = request.getHeader("bizName");
        String bizTableId = request.getHeader("bizTableId");
        String bizFieldName = request.getHeader("bizFieldName");
        try {
            WsFile wsFile = wsFileService.uploadFile(file, bizName, bizTableId, bizFieldName);
        } catch (Exception e) {
            log.error("上传附件入参:bizName:{},bizTableId:{},bizFieldName:{}", bizName, bizTableId, bizFieldName);
            log.error("上传附件异常:{}", e.getMessage(), e);
            return Result.error("上传附件异常");
        }
        return Result.OK();
    }

    /**
     * 批量上传员工附件
     * @param files
     * @param request
     * @return
     */
    @PostMapping("/uploadBatchEmployeeFile")
    public Result<?> uploadBatchEmployeeFile(@RequestParam("files") List<MultipartFile> files, HttpServletRequest request) {
        String bizName = request.getHeader("bizName");
        String bizTableId = request.getHeader("bizTableId");
        String bizFieldName = request.getHeader("bizFieldName");
        try {
            Map<String, List<MultipartFile>> map = files.stream().collect(Collectors.groupingBy(MultipartFile::getName));
            try {
                map.forEach((k, v) -> {
                    if (v.size() > 1) {
                        throw new JeecgBootException("请勿重复上传文件");
                    }
                });
            } catch (JeecgBootException e) {
                return Result.error("请勿重复上传同名文件");
            }
            for (MultipartFile file : files) {
                String name = file.getName();
                List<WsEmployee> list = employeeService.getByName(name);
                if (list !=null&&list.size() > 1){
                    return Result.error("存在同名员工情况,无法对应实际员工附件");
                }
            }
            for (MultipartFile file : files) {
                String name = file.getName();
                WsEmployee employee = employeeService.getByName(name).get(0);
                bizTableId = employee.getId();
                wsFileService.uploadFile(file, bizName, bizTableId, bizFieldName);
            }
        } catch (Exception e) {
            log.error("批量上传异常:{}", e.getMessage(), e);
            return Result.error("批量上传异常");
        }
        return Result.OK("批量上传成功！");
    }

    /**
     * 文件下载
     *
     * @param id 文件ID
     * @return 文件资源
     */
    @AutoLog(value = "文件下载")
    @ApiOperation(value="文件下载", notes="文件下载")
    @GetMapping(value = "/download")
    public HttpServletResponse download(String id,HttpServletResponse response) {
        try {
            WsFile wsFile = wsFileService.getById(id);
            if (wsFile == null) {
                response.setStatus(HttpServletResponse.SC_NOT_FOUND);
                response.getWriter().write("文件不存在");
                return response;
            }
            String filePath = wsFile.getFilePath();
            // path是指欲下载的文件的路径。
            File file = new File(filePath);
            if (!file.exists()) {
                response.setStatus(HttpServletResponse.SC_NOT_FOUND);
                response.getWriter().write("文件不存在");
                return response;
            }
            // 取得文件名。
            String filename = file.getName();
            // 取得文件的后缀名。
            String ext = filename.substring(filename.lastIndexOf(".") + 1).toUpperCase();
            // 以流的形式下载文件。
            FileInputStream fileInputStream = new FileInputStream(filePath);
            InputStream fis = new BufferedInputStream(fileInputStream);
            byte[] buffer = new byte[fis.available()];
            fis.read(buffer);
            fis.close();
            // 清空response
            response.reset();
            // 设置response的Header
            response.addHeader("Content-Disposition", "attachment;filename=" + new String(filename.getBytes()));
            response.addHeader("Content-Length", "" + file.length());
            OutputStream toClient = new BufferedOutputStream(response.getOutputStream());
            response.setContentType("application/octet-stream");
            toClient.write(buffer);
            toClient.flush();
            toClient.close();
            fileInputStream.close();
        } catch (Exception e) {
            log.error("文件下载失败");
            try {
                response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
                response.getWriter().write("文件下载失败");
            } catch (IOException ioException) {
                ioException.printStackTrace();
            }
        }
        return response;
    }

    /**
     * 文件删除
     */
    @AutoLog(value = "文件删除")
    @ApiOperation(value="文件删除", notes="文件删除")
    @DeleteMapping(value = "/deleteFile")
    public Result<?> deleteFile(String id) {
        try {
            wsFileService.deleteFile(id);
        }catch (Exception e){
            return Result.error("文件删除失败");
        }
        return Result.OK();
    }
    @Autowired
    private IWsCompanyService wsCompanyService;

    /**
     * 财务报表文件下载
     *
     * @param dto
     * @return 文件资源
     */
    @AutoLog(value = "财务报表文件下载")
    @ApiOperation(value="财务报表文件下载", notes="财务报表文件下载")
    @GetMapping(value = "/cwbbDownload")
    public HttpServletResponse download(CwbbDownloadDto dto, HttpServletResponse response) {
        try {
            String companyName = dto.getCompanyName();
            Date skssqq = dto.getSkssqq();
            Date skssqz = dto.getSkssqz();
            WsCompany wsCompany = wsCompanyService.getOneCwbb(companyName, skssqq, skssqz);
            String bizName = dto.getBizName();
            String id  = "";
            if (WsFileEnum.WS_CWBB_XJLLB.getBizName().equals(bizName)){
                id = wsCompany.getXjllbFileId();
            }else if (WsFileEnum.WS_CWBB_LRB.getBizName().equals(bizName)){
                id = wsCompany.getLrbFileId();
            }else if (WsFileEnum.WS_CWBB_ZCFZB.getBizName().equals(bizName)){
                id = wsCompany.getZcfzbFileId();
            }
            WsFile wsFile = wsFileService.getById(id);
            if (wsFile == null) {
                response.setStatus(HttpServletResponse.SC_NOT_FOUND);
                response.getWriter().write("文件不存在");
                return response;
            }
            String filePath = wsFile.getFilePath();
            // path是指欲下载的文件的路径。
            File file = new File(filePath);
            if (!file.exists()) {
                response.setStatus(HttpServletResponse.SC_NOT_FOUND);
                response.getWriter().write("文件不存在");
                return response;
            }
            // 取得文件名。
            String filename = file.getName();
            // 取得文件的后缀名。
            String ext = filename.substring(filename.lastIndexOf(".") + 1).toUpperCase();
            // 以流的形式下载文件。
            FileInputStream fileInputStream = new FileInputStream(filePath);
            InputStream fis = new BufferedInputStream(fileInputStream);
            byte[] buffer = new byte[fis.available()];
            fis.read(buffer);
            fis.close();
            // 清空response
            response.reset();
            // 设置response的Header
            response.addHeader("Content-Disposition", "attachment;filename=" + new String(filename.getBytes()));
            response.addHeader("Content-Length", "" + file.length());
            OutputStream toClient = new BufferedOutputStream(response.getOutputStream());
            response.setContentType("application/octet-stream");
            toClient.write(buffer);
            toClient.flush();
            toClient.close();
            fileInputStream.close();
        } catch (Exception e) {
            log.error("文件下载失败");
            try {
                response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
                response.getWriter().write("文件下载失败");
            } catch (IOException ioException) {
                ioException.printStackTrace();
            }
        }
        return response;
    }


    /**
     * 模板文件下载
     *
     * @param templateBizCode
     * @return 文件资源
     */
    @AutoLog(value = "模板文件下载")
    @ApiOperation(value="模板文件下载", notes="模板文件下载")
    @GetMapping(value = "/downloadTemplate")
    public HttpServletResponse downloadTemplate(String templateBizCode,HttpServletResponse response) {
        try {
            WsFileTemplateEnum templateEnum = WsFileTemplateEnum.getByTemplateBizCode(templateBizCode);
            if (templateEnum == null){
                response.setStatus(HttpServletResponse.SC_NOT_FOUND);
                response.getWriter().write("文件不存在");
                return response;
            }
            String id = templateEnum.getFileId();
            WsFile wsFile = wsFileService.getById(id);
            if (wsFile == null) {
                response.setStatus(HttpServletResponse.SC_NOT_FOUND);
                response.getWriter().write("文件不存在");
                return response;
            }
            String filePath = wsFile.getFilePath();
            // path是指欲下载的文件的路径。
            File file = new File(filePath);
            if (!file.exists()) {
                response.setStatus(HttpServletResponse.SC_NOT_FOUND);
                response.getWriter().write("文件不存在");
                return response;
            }
            // 取得文件名。
            String filename = file.getName();
            // 取得文件的后缀名。
            String ext = filename.substring(filename.lastIndexOf(".") + 1).toUpperCase();
            // 以流的形式下载文件。
            FileInputStream fileInputStream = new FileInputStream(filePath);
            InputStream fis = new BufferedInputStream(fileInputStream);
            byte[] buffer = new byte[fis.available()];
            fis.read(buffer);
            fis.close();
            // 清空response
            response.reset();
            // 设置response的Header
            response.addHeader("Content-Disposition", "attachment;filename=" + new String(filename.getBytes()));
            response.addHeader("Content-Length", "" + file.length());
            OutputStream toClient = new BufferedOutputStream(response.getOutputStream());
            response.setContentType("application/octet-stream");
            toClient.write(buffer);
            toClient.flush();
            toClient.close();
            fileInputStream.close();
        } catch (Exception e) {
            log.error("文件下载失败");
            try {
                response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
                response.getWriter().write("文件下载失败");
            } catch (IOException ioException) {
                ioException.printStackTrace();
            }
        }
        return response;
    }
}
